package com.webserver.core;

import com.webserver.core.annotations.Controller;
import com.webserver.core.annotations.RequestMapping;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;


/**
 * 该类用于维护请求路径与对应的业务处理类的方法
 */
public class HandlerMapping {

    /**
     * 保存每一个请求路径与对应的业务处理方法
     * key：请求路径
     * value：处理该请求的业务方法
     *
     * 例如：
     * key：/myweb/regUser
     * value:MethodMapping{
     *     Object Controller => UserController的实例
     *     Method method =>reg方法
     * }
     */
    private static Map<String ,MethodMapping>mapping=new HashMap<>();
    static {
        try {
            initMapping();
        } catch (URISyntaxException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }
    private static void initMapping() throws URISyntaxException, ClassNotFoundException, IllegalAccessException, InstantiationException {
        /*
            1:扫描com.webserver.controller包下的所有类
            2：利用反射机制加载这些类的类对象
            3：判断该类是否使用注解@Controller标注，没有的则忽略
               实例化当前Controller备用（第五步用）
            4：扫描该类中所有的方法，并判断该方法是否使用注解@RequestMapping标注，没有的忽略
            5：将注解@RequestMapping中的参数获取到（该方法对应的请求路径）并作为key。
              将第三步创建Collection实例并和当前方法对象（Method对象）组成一个MethodMapping作为value
              存入到mapping这个Map
         */
        File dir = new File(
                HandlerMapping.class.getClassLoader().getResource("./com/webserver/controller/").toURI()
        );
        File[]subs=dir.listFiles(f->f.getName().endsWith(".class"));
        for (File sub:subs) {
            String fileName = sub.getName();
            String className = fileName.substring(0, fileName.indexOf("."));
            Class cls = Class.forName("com.webserver.controller." + className);
            if (cls.isAnnotationPresent(Controller.class)){
                Object obj=cls.newInstance();
                Method[] methods=cls.getDeclaredMethods();
                for (Method method:methods
                     ) {
                    MethodMapping mm=new MethodMapping(obj,method);
                    if (method.isAnnotationPresent(RequestMapping.class)){
                        RequestMapping rm=method.getAnnotation(RequestMapping.class);
                        mapping.put(rm.value(),mm);
                    }
                }
            }
        }



        System.out.println(mapping);
    }
    public static MethodMapping getMethods(String path){
        return mapping.get(path);
    }

    /**
     * 当前类的每一个实例用于记录一个业务方法以及该方法所属的Controller对象
     */
    public static class MethodMapping{
        private Object controller;
        private Method method;

        public MethodMapping(Object controller, Method method) {
            this.controller = controller;
            this.method = method;
        }

        public Object getController() {
            return controller;
        }

        public void setController(Object controller) {
            this.controller = controller;
        }

        public Method getMethod() {
            return method;
        }

        public void setMethod(Method method) {
            this.method = method;
        }

    }

    public static void main(String[] args) {

    }
}
